package events;

import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CosEventComm.Disconnected;
import org.omg.CosEventComm.PushSupplierPOA;

/**
* Clase wrapper para un emisor de eventos. Para hacer uso
* de esta clase hay que heredar de ella e implementar el metodo
* "disconnect_push_supplier". Las clases que heredan de esta tienen que
* llamar a su constructor.
*
* @author Carlos Rodriguez Dominguez
*/
public abstract class EventSupplier extends PushSupplierPOA {
	
	private final int RETRIES = 100;
	protected org.omg.CORBA.ORB orb; /**< Puntero al orbe asociado al emisor de eventos */
	protected org.omg.CosEventChannelAdmin.EventChannel channel; /**< Canal de eventos */
	protected org.omg.CosEventChannelAdmin.SupplierAdmin supplier_admin; /**< Administrador del emisor de eventos */
  	protected org.omg.CosEventChannelAdmin.ProxyPushConsumer proxy_consumer; /**< Proxy con el consumidor de eventos */
	
	public EventSupplier(org.omg.CORBA.ORB __orb)
	{
		orb = __orb;
		
		create_supplier();
	}

	protected void disconnect_from_push_consumers()
	{
		int i;
		
		for(i=0; i<RETRIES; i++) 
		{
			try {
		    	proxy_consumer.disconnect_push_consumer();
		      	break;
		   	}
		   	catch (COMM_FAILURE ex) 
			{
	        	System.out.println("Fallo de conexion: Reintento "+(i+1)+" de "+RETRIES);
				if ((i+1) >= RETRIES)
				{
					System.exit(1);
				}
		   	}
		}
	}

	/**
	* Crea el emisor de eventos
	*/
	protected void create_supplier()
	{
		try {
			org.omg.PortableServer.POA rootPoa;
			org.omg.CORBA.Object obj = orb.resolve_initial_references("RootPOA");
			rootPoa = org.omg.PortableServer.POAHelper.narrow(obj);
			
			org.omg.PortableServer.POAManager pman = rootPoa.the_POAManager();
			pman.activate();
			
			org.omg.CosNaming.NamingContext rootContext;
			obj = orb.resolve_initial_references("NameService");
			rootContext = org.omg.CosNaming.NamingContextHelper.narrow(obj);

			org.omg.CosNaming.NameComponent[] name = new org.omg.CosNaming.NameComponent[1];
			name[0] = new org.omg.CosNaming.NameComponent();
			name[0].id = "EventChannel";
			name[0].kind = "EventChannel";

			obj = rootContext.resolve(name);
			channel = org.omg.CosEventChannelAdmin.EventChannelHelper.narrow(obj);
		}
		catch(org.omg.CORBA.SystemException e) 
		{
			System.out.println(e.getMessage());
			System.exit(1);
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			System.exit(1);
		}

		int i;
		for (i=0; i<RETRIES; i++)
		{
			try {
				supplier_admin = channel.for_suppliers();
			   	break;
			}
			catch (COMM_FAILURE ex) 
			{
				System.out.println("Fallo de conexion: Reintento "+(i+1)+" de "+RETRIES);
				if ((i+1) >= RETRIES)
				{
					System.exit(1);
				}
			}
		}
		
		for (i=0; i<RETRIES; i++)
	  	{
			try {
	        	proxy_consumer = supplier_admin.obtain_push_consumer();
				break;
			}
	    	catch (COMM_FAILURE ex) 
			{
	        	System.out.println("Fallo de conexion: Reintento "+(i+1)+" de "+RETRIES);
				if ((i+1) >= RETRIES)
				{
					System.exit(1);
				}
			}
		}

		for (i=0; i<RETRIES; i++)
	  	{
	     	try {
	        	proxy_consumer.connect_push_supplier(this._this(orb));
	        	break;
	     	}
	     	catch (BAD_PARAM ex) 
			{
				System.out.println("BAD_PARAM: "+ex.getMessage());
			    System.exit(1);
	     	}
	     	catch (org.omg.CosEventChannelAdmin.AlreadyConnected ex) 
			{
				break;
	     	}
	     	catch (COMM_FAILURE ex) 
			{
	        	System.out.println("Fallo de conexion: Reintento "+(i+1)+" de "+RETRIES);
				if ((i+1) >= RETRIES)
				{
					System.exit(1);
				}
	     	}
	  	}
	}
	
	/**
	* Emite un evento.
	*
	* @param data Evento a emitir
	*/
	public void push(org.omg.CORBA.Any data)
	{
		try {
			proxy_consumer.push(data);
		} catch (Disconnected e) {
			e.printStackTrace();
		}
	}
}
